Thanks for taking the time to read this, for a bit of background I'm using React 17 with Webpack.
Within my main component, I have many conditional child components (dependant upon my state) - which for performance reasons I want to Lazy Load (only when and if needed).
However, using my current solution any time my "ParentComponent" is re-rendered (state change), the Child Component is too re-loaded (regardless if "state.somevalue" has been updated or not) and loses its own state and flickers where the HTML is re-rendered.
Here is an example:
class ParentComponent extends React.Component {
__renderChildComponent1(){
const ChildComponent = React.lazy(() =>
import(
/* webpackMode: "lazy" */
/* webpackChunkName: "childa" */ './ChildA.jsx'
)
);
return (
<Suspense fallback="">
<ChildComponent myprop={ this.state.somevalue } />
</Suspense>
)
}
__renderChildComponent2(){
const ChildComponent = React.lazy(() =>
import(
/* webpackMode: "lazy" */
/* webpackChunkName: "childb" */ './ChildB.jsx'
)
);
return (
<Suspense fallback="">
<ChildComponent myprop={ this.state.somevalue } />
</Suspense>
)
}
__renderChildComponent(){
switch(this.state.myoption){
case "1":
return this.__renderChildComponent1();
break;
case "2":
return this.__renderChildComponent2();
break;
default:
return null;
break;
}
}
render(){
<div className="component-a">
{ this.__renderChildComponent() }
</div>
}
}
I've tried to instead assign my Child Component against a property of my ParentComponent e.g.:
this.ChildComponent = false;
if(!this.childComponent){
const ChildComponent = React.lazy(() =>
import(
/* webpackMode: "lazy" */
/* webpackChunkName: "childb" */ './ChildB.jsx'
)
);
this.childComponent = (
<Suspense fallback="">
<ChildComponent myprop={ this.state.somevalue } />
</Suspense>
)
} else {
return this.childComponent;
}
But upon doing this my childComponent no longer recieves state updates from its parent.
What's the best way of achieving this?
Thanks in Advance.
I'm not sure if this a good pattern, but the solution that came to my mind is having an array in state for children components:
this.state.children=[null,null] // initially they are two indexes of null, for the two children.
every time this.state.myoption is updated, check if the corresponding child is null, and if it is, lazy load.
componentDidUpdate() {
if (this.state.children[this.state.myoption] === null) {
import("PATH").then((component) => {
const newChildrenArray = [...this.state.children];
newChildrenArray[this.state.myoption] = component;
this.setState({ children: newChildrenArray });
});
}
}
finally, inside render, check if the needed component is available, and render it.
render(){
let Component = this.state.children[this.state.myoption]
<div className="component-a">
{Component?<Component/>:""}
</div>